#include "mpdbackend.h"

uint mpdbackend::features()
{
    return AUDIO_BACKEND_INFO | AUDIO_BACKEND_CONTROL | AUDIO_BACKEND_ADVANCED_CONTROL | AUDIO_BACKEND_COLLECTION;
}

void mpdbackend::init()
{
        QString hostname = "::1";
        uint port = 6600;
        QString password = "";
    
        mpd = mpd_new(hostname.toUtf8().data(), port, password.toUtf8().data());

        if(mpd_connect(mpd) != MPD_OK){
                qDebug("Connection failed");
        }else{
                qDebug("Connection etablished");
        }

        //qDebug() << this;
        mpd_signal_connect_status_changed(mpd,status_changedCB, (void*)this);

        QTimer *timer = new QTimer(this);
        connect(timer, SIGNAL(timeout()), this, SLOT(timerTimeout()));
        timer->start(500);
}

QList<QString> mpdbackend::getAllArtists()
{
    QList<QString> artists;

    MpdData *data = mpd_database_get_artists(mpd);

    while(data != NULL){
        //qDebug() << data->tag;
        artists.append(data->tag);
        data = mpd_data_get_next(data);
    }
    mpd_data_free(data);

    return artists;

}

QList<Song*> * mpdbackend::getAllSongs()
{
    QList<Song *> * songs = new QList<Song *>();

    MpdData *data = mpd_database_get_complete(mpd);

    while(data != NULL){
        //qDebug() << data->tag;
        Song * tmp = new Song(QString::fromUtf8(data->song->file),
                              QString::fromUtf8(data->song->title),
                              QString::fromUtf8(data->song->artist),
                              QString::fromUtf8(data->song->album),
                              QString::fromUtf8(data->song->track),
                              QString::fromUtf8(data->song->name),
                              data->song->id);
        songs->append(tmp);
        data = mpd_data_get_next(data);
    }
    mpd_data_free(data);

    return songs;
}

QList<QString> mpdbackend::getAllAlbums()
{
    QList<QString> albums;

    MpdData *data = mpd_database_get_albums(mpd, NULL);

    while(data != NULL){
        //qDebug() << data->tag;
        albums.append(data->tag);
        data = mpd_data_get_next(data);
    }
    mpd_data_free(data);

    return albums;
}

QList<QString> mpdbackend::getAlbumsFromArtist(QString artist)
{
    QList<QString> albums;

    MpdData *data = mpd_database_get_albums(mpd, artist.toUtf8().data());

    while(data != NULL){
        //qDebug() << "DEBUG getAlbumsFromArtist()" << artist << " => " << data->tag;
        albums.append(data->tag);
        data = mpd_data_get_next(data);
    }
    mpd_data_free(data);

    return albums;
}

QList<Song*> * mpdbackend::getSongsFromAlbum(Album * album)
{
    QList<Song*> * songsList = new QList<Song*>();

    MpdData  * data;

    mpd_database_search_start(mpd,1);
    mpd_database_search_add_constraint(mpd, MPD_TAG_ITEM_ALBUM, album->getName().toUtf8());

    for(data = mpd_database_search_commit(mpd); data != NULL ; data = mpd_data_get_next(data)){
        //qDebug() << "DEBUG getSongsFromAlbum(" << album << "=> " << data->song->title;
        Song * tmp = new Song(QString::fromUtf8(data->song->file),
                              QString::fromUtf8(data->song->title),
                              QString::fromUtf8(data->song->artist),
                              QString::fromUtf8(data->song->album),
                              QString::fromUtf8(data->song->track),
                              QString::fromUtf8(data->song->name),
                              data->song->id);
        tmp->setAlbum(album);
        tmp->setArtist(album->getArtist());
        songsList->append(tmp);
    }
    mpd_data_free(data);

    //for(int i = 0;i < songsList.size();i++){
    //    qDebug() << "tmp => " << songsList.at(i).title;
    //}

    return songsList;
}

QList<Song*> * mpdbackend::getSongsFromArtist(Artist * artist)
{
    QList<Song*> * songsList = new QList<Song*>();

    MpdData  * data;

    mpd_database_search_start(mpd,1);
    mpd_database_search_add_constraint(mpd, MPD_TAG_ITEM_ARTIST, artist->getName().toUtf8());

    for(data = mpd_database_search_commit(mpd); data != NULL ; data = mpd_data_get_next(data)){
        Song * tmp = new Song(QString::fromUtf8(data->song->file),
                              QString::fromUtf8(data->song->title),
                              QString::fromUtf8(data->song->artist),
                              QString::fromUtf8(data->song->album),
                              QString::fromUtf8(data->song->track),
                              QString::fromUtf8(data->song->name),
                              data->song->id);
        tmp->setArtist(artist);
        songsList->append(tmp);
    }
    mpd_data_free(data);

    return songsList;
}

void mpdbackend::timerTimeout()
{
    mpd_status_update(mpd);
}

void status_changedCB(MpdObj *mi, ChangedStatusType what, void* userData)
{
    //qDebug() << userData;
    ((mpdbackend*)userData)->statusChanged(what);    //hack to call a class function so we can emit signals
}

void mpdbackend::statusChanged(ChangedStatusType what)
{


    if(what&MPD_CST_PLAYLIST){
                // act on playlist change

    }if(what&MPD_CST_SONGPOS){
                // act on song pos change

    }if(what&MPD_CST_SONGID){
                // act on song change
                emit this->songChanged();
                qDebug() << "statusChanged => song";

    }if(what&MPD_CST_DATABASE){
                // act on db change

    }if(what&MPD_CST_UPDATING){
                // act on db update change

    }if(what&MPD_CST_VOLUME){
                // act on volume change

    }if(what&MPD_CST_TOTAL_TIME){
                // act on total song time change

    }if(what&MPD_CST_ELAPSED_TIME){
                // act on elapsed song time change

    }if(what&MPD_CST_CROSSFADE){
                // act on crossfade time change

    }if(what&MPD_CST_RANDOM){
                // act on random state change
                emit this->randomStatusChanged(this->getRandom());
                qDebug() << "statusChanged => random";

    }if(what&MPD_CST_REPEAT){
                // act on repeat state change
                emit this->repeatStatusChanged(this->getRepeat());
                qDebug() << "statusChanged => repeat";

    }if(what&MPD_CST_STATE){
                // act on player state change
                emit this->stateChanged(this->isPlaying());
                qDebug() << "statusChanged => state";

    }if(what&MPD_CST_BITRATE){
                // act on song bitrate change

    }if(what&MPD_CST_STORED_PLAYLIST){
                // act on queue change

    }if(what&MPD_CST_SERVER_ERROR){
                // act on server error

    }
}

bool mpdbackend::play()
{
        if(mpd_player_play(mpd) == MPD_OK)
                return true;
        else
                return false;
}

bool mpdbackend::play(uint id)
{
        if(mpd_player_play_id(mpd, id) == MPD_OK)
                return true;
        else
                return false;
}

bool mpdbackend::play(Song * song)
{
    qDebug() << "playSong!!!";

    int id = -1;
    QList<Song*> * songs;

    if(song->getAlbum() == NULL){
        if(song->getArtist() == NULL){
            qDebug() << "Full collection add currently broken";
            return false;
            //songs = collection->getArtists()->at(0)->getAlbums()->at(0)->getSongs();
        }else{
            songs = song->getArtist()->getAlbums()->at(0)->getSongs();
        }
    }else{
        songs = song->getAlbum()->getSongs();
    }

    mpd_playlist_clear(this->mpd);

    Song * toAdd;
    foreach(toAdd,*songs){
        if(toAdd == song){
            id = mpd_playlist_add_get_id(this->mpd,toAdd->file.toUtf8().data());
        }else{
            mpd_playlist_queue_add(this->mpd,toAdd->file.toUtf8().data());
        }
    }

    mpd_playlist_queue_commit(this->mpd);
    this->play(id);
    return true;
}

bool mpdbackend::stop()
{
        if(mpd_player_stop(mpd) == MPD_OK)
                return true;
        else
                return false;
}

bool mpdbackend::next()
{
        if(mpd_player_next(mpd) == MPD_OK)
                return true;
        else
                return false;
}

bool mpdbackend::prev()
{
        if(mpd_player_prev(mpd) == MPD_OK)
                return true;
        else
                return false;
}

bool mpdbackend::pause()
{
        if(mpd_player_pause(mpd) == MPD_OK)
                return true;
        else
                return false;
}

bool mpdbackend::togglePause()
{
    if(this->isPlaying()){
        return this->pause();
    }else{
        return this->play();
    }
}

bool mpdbackend::setVolume(int value)
{
        if(mpd_status_set_volume(mpd,value) == MPD_OK)
                return true;
        else
                return false;
}

uint mpdbackend::getVolume()
{
        return mpd_status_get_volume(mpd);
}

QString mpdbackend::getCurrentSongTitle(){
        currentSong = mpd_playlist_get_current_song(mpd);

        return QString::fromUtf8(currentSong->title);
}

QString mpdbackend::getCurrentSongArtist(){
        currentSong = mpd_playlist_get_current_song(mpd);

        return QString::fromUtf8(currentSong->artist);
}

QString mpdbackend::getCurrentSongAlbum(){
        currentSong = mpd_playlist_get_current_song(mpd);

        return QString::fromUtf8(currentSong->album);
}

bool mpdbackend::isPlaying()
{
        if(mpd_player_get_state(mpd) == MPD_PLAYER_PLAY){
                qDebug() << "isPlaying";
                return true;
        }else{
                qDebug() << "isNotPlaying";
                return false;
        }
}

bool mpdbackend::isPaused()
{
        if(mpd_player_get_state(mpd) == MPD_PLAYER_PAUSE){
                qDebug() << "isPaused";
                return true;
        }else{
                qDebug() << "isNotPaused";
                return false;
        }
}

bool mpdbackend::seek(int sec)
{
        if(mpd_player_seek(mpd,sec) != MPD_PLAYER_STOP){
                return true;
        }else{
                return false;
        }
}

int mpdbackend::getElapsedTime()
{
        return mpd_status_get_elapsed_song_time(mpd);
}

bool mpdbackend::setRandom(bool status)
{
        if(status == true){
            return mpd_player_set_random(mpd,1);
        }else{
            return mpd_player_set_random(mpd,0);
        }
}

bool mpdbackend::toggleRandom()
{
        if(this->getRandom()){
            return mpd_player_set_random(mpd,0);
        }else{
            return mpd_player_set_random(mpd,1);
        }
}

bool mpdbackend::getRandom()
{
    if(mpd_player_get_random(mpd) == 1){
        return true;
    }else{
        return false;
    }
}

bool mpdbackend::setRepeat(bool status)
{
        if(status == true){
            return mpd_player_set_repeat(mpd,1);
        }else{
            return mpd_player_set_repeat(mpd,0);
        }
}

bool mpdbackend::toggleRepeat()
{
        if(this->getRepeat()){
            return mpd_player_set_repeat(mpd,0);
        }else{
            return mpd_player_set_repeat(mpd,1);
        }
}


bool mpdbackend::getRepeat()
{
    if(mpd_player_get_repeat(mpd) == 1){
        return true;
    }else{
        return false;
    }
}

Q_EXPORT_PLUGIN2(tsmpc_mpdbackend, mpdbackend)
